#pragma once

#include <string>
#include <vector>
#include <thread>
#include <mutex>
#include <functional>
#include <unordered_set>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

class TcpConnection {
public:
    using MessageHandler = std::function<void(const std::string&, TcpConnection*)>;
    
    TcpConnection(int sock_fd, MessageHandler handler);
    ~TcpConnection();
    
    void start();
    void send(const std::string& message);
    bool is_connected() const { return connected_; }
    int get_fd() const { return sock_fd_; }

private:
    void handle_read();
    
    int sock_fd_;
    bool connected_;
    MessageHandler message_handler_;
    std::mutex write_mutex_;
    std::thread read_thread_;
    static constexpr size_t BUFFER_SIZE = 4096;
};

class TcpServer {
public:
    TcpServer(int port);
    ~TcpServer();
    
    void start();
    void stop();
    void set_message_handler(TcpConnection::MessageHandler handler);
    void broadcast(const std::string& message);

private:
    void accept_connections();
    
    int server_fd_;
    int port_;
    bool running_;
    std::thread accept_thread_;
    TcpConnection::MessageHandler message_handler_;
    std::unordered_set<TcpConnection*> connections_;
    std::mutex connections_mutex_;
}; 